package org.NooLab.itexx.retrieval;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.NooLab.itexx.ITexxWindowIntf;
import org.NooLab.itexx.app.gui.definition.ITexxWindowGui;
import org.NooLab.itexx.app.gui.definition.ITexxWindowGuiIntf;
import org.NooLab.itexx.browser.DjBrowserHostIntf;
import org.NooLab.itexx.stuctures.RequestItem;

import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.strings.StringsUtil;

import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserNavigationParameters;


/**
 * 
 * initially, we have to go to the google page without search request, 
 * and log off from the google account !!!
 * 
 * The object RetrievalEngine is transported by the RequestItem itself, and the
 * RequestItem is created upon entering a search string to the box, OR programmatically;
 * 
 * The Engine and the Item are issued together to the RequestSearchHandler in the following way
 * 
 * RequestSearchHandler rsh  ;
 * rsh = itexxModel.getSearchRequest();
 * rsh.update RequestEntries( new RetrievalEngine(itexxModel.getTexxWindowApp(), 1, RetrievalEngineIntf._HOST_GOOGLE ), requestItem) ;
 *
 * finally, from here we transfer it to the object DjBrowserHost/Intf, where the
 * SwingWorker for calling JWebBrowser is hosted
 * 
 */
public class RetrievalEngine implements RetrievalEngineIntf{

	ITexxWindowIntf    mainApp;
	ITexxWindowGuiIntf appGui;
	
	int mode = -1, host = -1;
	boolean requestPerformerIsWorking = false;

	int googleItemsCount = 10;
	RequestUrlManager requestUrls ;
	
	RequestPreProcessingIntf  requestPreProcessing;
	
	PrintLog out = new PrintLog(2, false);

	/**
	 * 
	 * @param iTexxWindowIntf
	 * @param mode
	 *            0=normal, 1=display only the main body (content panel/div )
	 *            -1=raw -> direct display of retrieval
	 * @param _host
	 *            in some contexts (primary search), we know of the hosts that
	 *            we are going to query
	 */
	public RetrievalEngine(ITexxWindowIntf app, int mode, int _host) {
		
		mainApp = app;
		appGui = mainApp.getWindowGui() ;
		
		host = _host;
		this.mode = mode;

		requestUrls = new RequestUrlManager( mainApp, this) ; 
	
		requestPreProcessing = new RequestPreProcessing( mainApp ) ;
		
		out.setPrefix("[Browser-Engine]");
	}

	public void perform( RequestItem requestItem ) {

		requestPerformerIsWorking = true;

		if ( isSearchEngine(host)){

			int pagesCount = requestItem.getCountOfNextPages() ;
			if (pagesCount<1)pagesCount=1;
			if (pagesCount>500)pagesCount=500; // TODO: use a constant here!!! would be 5000 results 
			
			// again: RequestItems etc are used ONLY against search engines!!! 
			(new RequestPerformer(this, requestItem)).querySearchEngine( host, pagesCount );
			
		}else{
			(new RequestPerformer(this, requestItem)).go();
		}

		while (requestPerformerIsWorking) {
			out.delay(50);
		}

	}

	private boolean isSearchEngine(int host) {
		// 
		boolean rB=false;
		
		rB = (host == RetrievalEngineIntf._HOST_GOOGLE ); 
		
		if (rB==false){
			rB = (host == RetrievalEngineIntf._HOST_BING );
		}
		if (rB==false){
			rB = (host == RetrievalEngineIntf._HOST_YAHOO );
		}
		
		return rB;
	}

	public RequestPreProcessingIntf getRequestPreProcessing() {
		return requestPreProcessing;
	}

	public void setRequestPreProcessing(RequestPreProcessingIntf requestPreProcessing) {
		this.requestPreProcessing = requestPreProcessing;
	}

}

class RequestPerformer {

	RetrievalEngine parentEngine;
	String searchStr;
	String url = "www.google.com" ;
	RequestItem requestItem;
	
	public RequestPerformer(RetrievalEngine parent, RequestItem requestItem) {
		searchStr = requestItem.getRequestStr();
		parentEngine = parent;
		this.requestItem = requestItem;
	}

	public void querySearchEngine() {
		querySearchEngine(RetrievalEngineIntf._HOST_GOOGLE,1);
	}
	
	public void querySearchEngine(int hostId, int pagesCount) {
		// 
		ArrayList<String> googleRequestUrls = new ArrayList<String>();
		ArrayList<String> bingRequestUrls   = new ArrayList<String>();
		
		String googleRequestUrl="",bingRequestUrl="";
		
		if ((searchStr==null) || (searchStr.length()<=1)){
			return;
		}
		parentEngine.out.print(2, "querySearchEngine() -> "+searchStr);
		
		
		
		googleRequestUrl = parentEngine.requestUrls.prepareSearchEngineUrl(searchStr, "google", 0); // pagesCount
		
		bingRequestUrl   = parentEngine.requestUrls.prepareSearchEngineUrl(searchStr,"bing", 0);
		
		// https://www.google.ch/search?num=100&hl=de&newwindow=1&q=processing+p5&oq=processing+p5
		
		// http://www.bing.com/search?q=putnam+progam&go=&qs=ds&form=QBLH&filt=all
		
		// http://www.bing.com/search?q=putnam+progam&go=&qs=ds&filt=all&first=81
		
		// app.webBrowser.navigate(baseurl);
		
		for (int g=0;g<googleRequestUrls.size();g++){
			
			
		}// g -> all google urls
		
		googleRequestUrl = googleRequestUrls.get(0);
		if (googleRequestUrl.length()>0 ){
			
			parentEngine.out.print(2, "get results from search url from google...");
			parentEngine.out.print(2, "-> "+ googleRequestUrl);
			// parentEngine.mainApp.webBrowser.navigate( googleRequestUrl );
			DjBrowserHostIntf wbHost = parentEngine.mainApp.getAppCommons().getHostList().get(0);
			
// pagesCount=1;
if ((pagesCount>30) && (parentEngine.googleItemsCount>50)){
	pagesCount = (int)(((double)pagesCount)/((double)parentEngine.googleItemsCount));
}
			if (pagesCount>1){
				wbHost.startCollecting();
			}
			
			for (int p=0;p<pagesCount;p++){
				
				if (p>0){
					// we have some delay, additionally we exchange the user-agent for each request
					// in order to prevent captcha robot blocking 
					parentEngine.out.delay(3500 + (int)Math.round(700*Math.random()-0.3));
				}  // FIXME: these should be constants !!!
				
				/* note that "googleItemsCount" is dynamic !!
				 * it is better to have 100 results per page, but the user must do this, we only can check it from the results on the first page 
				 */
				googleRequestUrl = parentEngine.requestUrls.prepareSearchEngineUrl(searchStr, "google", p* parentEngine.googleItemsCount);
				
				parentEngine.out.print(4, "Browser (use) = "+ wbHost.toString());
				
				PageIntf page = new Page();
				
				// used in ResultsDigester for deciding whether to collect individual pages
				// or stop collecting
				page.setCurrentCollectionIndex(p);
				page.setExpectedCollectionSize(pagesCount); 
				page.setContextUrl(googleRequestUrl);
				page.setIsQueryUrl(true);
				page.setSecret("111");
				page.setRequestID( requestItem.getGuidStr() ) ;
				
				wbHost.setPageReference(page); 
											parentEngine.out.print(3,"sending url to BrowserHost (index:"+p+"), page object : "+(page.getClass() )+"...");
				// wb.retrieve(googleRequestUrl);
			    wbHost.getListener().setContextUrl( googleRequestUrl ) ;					
				wbHost.retrieve(page,"itexx");
			}// p -> all pages
			
			if (wbHost.isCollecting()){
				wbHost.stopCollecting();
			}
		}
		
		
		if (bingRequestUrl.length()>0){
			parentEngine.out.print(2, "get results from search url from google...");
			
		}
	}

	public void go() {
		
		
		parentEngine.out.print(2, "Retrieval-Engine now working on request string <" + searchStr + ">");

		BrowsePage page = new BrowsePage ();
		page.getPage(url);
		// url comes from external repository, definition in XML form, containing search engines
		
		
		parentEngine.out.delay(2000);
		parentEngine.requestPerformerIsWorking = false;
	}

}

class BrowsePage {

	String htmlStr="";
	Map<String, String> postDataMap = new HashMap<String, String>() ;

	public BrowsePage() {

	}

	public void addPostParameter( String key, String value){
		

		/*
		postDataMap.put("short_desc_type", "allwordssubstr");
		postDataMap.put("short_desc", "");
		postDataMap.put("bug_status", "NEW");
		postDataMap.put("product", "Platform");
		postDataMap.put("component", "SWT");
	    */
		postDataMap.put( key, value);
	}
	
	public String getPage( String url ) {
		return getPagebyGet( url ) ;
	}
	
	
	public String getPagebyGet( String url ) {
		htmlStr = "";
		// chrriis.dj.nativeswing.swtimpl.components.JWebBrowser
		JWebBrowser webBrowser = new JWebBrowser();
		
		webBrowser.navigate(url);
		
		htmlStr = webBrowser.getHTMLContent() ;
		// https://www.google.ch/search?num=100&hl=en&q=%22the+putnam+program%22&oq=%22the+putnam+program%22
		return htmlStr;
	}
	
	public String getPagebyCgiPost( String url ) {

		JWebBrowser webBrowser = new JWebBrowser();
		webBrowser.setBarsVisible(false);
		WebBrowserNavigationParameters parameters = new WebBrowserNavigationParameters();
		
		
		parameters.setPostData(postDataMap);
		// webBrowser.navigate("https://bugs.eclipse.org/bugs/buglist.cgi", parameters);
		webBrowser.navigate(url, parameters);
		
		htmlStr = webBrowser.getHTMLContent() ;
		
		return htmlStr;
	}
}
